home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_08_05
/
8n05035a
< prev
next >
Wrap
Text File
|
1990-04-17
|
13KB
|
288 lines
/*
prb.c - Packetized Ring Buffer demonstration
(c) Copyright 1989, 1990 Martin J. Stitt
*/
#include <alloc.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned char byte;
typedef unsigned int word;
typedef struct {
word prb_totbytes; /* define the ring buffer's size */
byte *prb_base; /* ptr to base of buffer */
byte *prb_head; /* head ptr - from which data is read */
byte *prb_tail; /* tail ptr - at which data is written */
word prb_free; /* amount of free space in the buffer */
word prb_eobofs; /* offset of byte just past the eob */
byte prb_packets; /* number of records in the buffer */
byte prb_use_rectype; /* indicates use of two byte headers */
word prb_overflow; /* indicates when a record is too large */
byte prb_max_dsize; /* maximum size for record's data */
} prb_type;
/*- prb_init -----------------------------------------------------------
entry parms: ptr to a partially initialized prb structure
prb_base must point to an allocated buffer
prb_totbytes must be its size
prb_use_rectype must be assigned
exit parms: function return value != 0 when the last buffer
offset is 0xFFFF
notes: call before writing and reading. can recall later to flush the
ring buffer. can ignore return value on sucessive calls.
------------------------------------------------------------------------*/
word prb_init(prb_type *b) {
b->prb_head = b->prb_base; /* initialize the pointers */
b->prb_tail = b->prb_base; /* to flush the buffer */
b->prb_free = b->prb_totbytes;
b->prb_packets = 0;
b->prb_max_dsize = 255-1; /* -1 for the header byte */
if(b->prb_use_rectype) b->prb_max_dsize--; /* if using 2 byte header */
b->prb_overflow = 0;
b->prb_eobofs = (word) b->prb_base + b->prb_totbytes;
return((b->prb_eobofs == 0) ? 1 : 0);
}
/*- prb_write_data ---------------------------------------------------------
entry parms: ptr to buffer structure
ptr to caller's data, size of caller's data
record type code (ignored if prb_use_rectype == 0)
exit parms: function return value != 0 if overflow
------------------------------------------------------------------------*/
word prb_write_data(prb_type *b, void *idata, byte dsize, byte rectype) {
byte csize; /* data bytes to xfer */
byte psize; /* total packet size */
word block1; /* bytes before wrap of tail */
byte need_wrap; /* flags need for a 2 part xfer */
word adjust_head; /* bytes to advance the head ptr */
word head2end; /* bytes before wrap of head */
if(dsize == 0) return(1); /* anything to insert? */
if(dsize > b->prb_max_dsize) return(1); /* don't allow oversized data */
psize = dsize+1; /* +1 for the pkt size header byte */
if(b->prb_use_rectype) { /* if using a record type */
psize++; /* account for header byte */
}
if(psize > b->prb_totbytes) { /* if record too large for buffer */
if(psize < b->prb_overflow) { /* record overflow unless another */
b->prb_overflow = psize; /* larger recorded */
}
return(1); /* indicate a problem */
}
while(psize > b->prb_free) { /* while not enough free room */
b->prb_free += *b->prb_head; /* adjust free to show deletion */
b->prb_packets--; /* adjust accounting of pkts */
adjust_head = *b->prb_head; /* fetch size of pkt to be deleted */
head2end = b->prb_eobofs - (word) b->prb_head; /* calc bytes till wrap */
if(adjust_head > head2end) { /* will deletion involve a wrap? */
adjust_head -= head2end; /* calc bytes in second portion */
b->prb_head = b->prb_base; /* wrap around */
}
b->prb_head += adjust_head; /* advance the head pointer */
if((word) b->prb_head == b->prb_eobofs) { /* if pkt deleted just fit */
b->prb_head = b->prb_base; /* need to wrap */
}
}
block1 = b->prb_eobofs - (word) b->prb_tail; /* calc size of 1st block */
b->prb_packets++; /* update accounting of pkts */
b->prb_free -= psize; /* update accounting of free space */
csize = psize-1; /* sub 1 for pkt size header byte */
*(b->prb_tail++) = psize; /* write header byte, advance tail */
need_wrap = 0; /* initialize flag */
if(psize > block1) { /* if won't all fit in 1st block */
need_wrap = 1; /* write remainder in 2nd block */
csize = block1-1; /* -1 for header already written */
if(csize == 0) { /* if block1 only had 1 byte */
b->prb_tail = b->prb_base; /* do the wrap now */
need_wrap = 0; /* don't need to wrap later */
csize = psize-1; /* -1 for header already written */
}
}
if(b->prb_use_rectype) { /* if type code to be inserted */
*(b->prb_tail++) = rectype; /* insert it now and advance tail */
csize--; /* account for type code */
if(csize == 0) { /* if block1 only had 2 bytes */
b->prb_tail = b->prb_base; /* do the wrap now */
need_wrap = 0; /* don't need to wrap later */
csize = psize-2; /* account for 2 bytes in header */
}
}
memmove(b->prb_tail,idata,csize); /* insert csize bytes into buffer */
b->prb_tail += csize; /* advance tail past new data */
if(need_wrap) { /* if more data left to insert */
b->prb_tail = b->prb_base; /* wrap the tail back around */
(byte) idata += csize; /* advance the caller's pointer */
memmove(b->prb_tail,idata,(psize-block1)); /* insert the remaining data */
b->prb_tail += (psize-block1);
}
if(b->prb_eobofs == (word) b->prb_tail) { /* if blk went just up to end */
b->prb_tail = b->prb_base; /* need to wrap tail back around */
}
return(0); /* indicate success */
}
/*- prb_read_rectype ---------------------------------------------------
entry parms: ptr to buffer structure
address of byte to receive rectype
exit parms: function return value is data size
0 means buffer is empty
notes: presumes all ring buffer records contain a rectype byte in
their header. if the buffer is empty, the rectype value returned
will be garbage.
------------------------------------------------------------------------*/
byte prb_read_rectype(prb_type *b, byte *rectype) {
byte *tptr; /* local scratch pointer */
if(b->prb_packets == 0) return(0); /* anything in buffer? */
tptr = b->prb_head + 1; /* point to the record type code */
if(b->prb_eobofs == (word) tptr) { /* need to wrap to read */
tptr = b->prb_base; /* the 2nd byte? */
}
*rectype = *tptr; /* transfer rectype to caller */
return(*b->prb_head-2); /* return the record size */
}
/*- prb_read_data -----------------------------------------------------------
entry parms: ptr to buffer structure
address of buffer to receive record contents
exit parms: function return value is data size
0 means buffer is empty
notes: presumes caller has referenced any recorded rectype and has
supplied a pointer to a large enough buffer. *prb_head can be
referenced to verify the size requirement.
------------------------------------------------------------------------*/
byte prb_read_data(prb_type *b, void *dest) {
byte dsize; /* data bytes in packet */
byte csize; /* bytes to transfer */
byte rsize; /* bytes left when need 2 xfers */
word block1; /* bytes before wrap */
if(b->prb_packets == 0) return(0); /* make sure buffer has data */
b->p